﻿/*
   Copyright 2012 University of Southampton

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using uk.ac.soton.ses.DAL;
using System.Web;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI.WebControls;

namespace uk.ac.soton.ses.layouts
{
    public partial class ExperimentTypes : LayoutsPageBase
    {
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            this.view_ExperimentTypes.SelectedIndexChanged += new EventHandler(view_ExperimentTypes_SelectedIndexChanged);
            this.view_LinkedTemplates.RowCommand += new GridViewCommandEventHandler(view_Templates_RowCommand);
            this.view_NonLinkedExperiments.RowCommand += new GridViewCommandEventHandler(view_Templates_RowCommand);

            this.Page.AddHDCStylesheet();
        }

        void view_Templates_RowCommand(object sender, GridViewCommandEventArgs e)
        {
            //Get the index of the row that was clicked
            int rowindex;
            if (int.TryParse((string)e.CommandArgument, out rowindex ))
            {
                //Get the ID for the experiment selected
                int? typeid = view_ExperimentTypes.SelectedDataKey["ID"] as int?;
                switch (e.CommandName)
                {
                    case "Unlink":
                        {
                            int? experimentid = view_LinkedTemplates.DataKeys[(int)rowindex]["ID"] as int?;
                            if (experimentid != null && typeid != null)
                            {
                                this.UnlinkExperimentFromType((int)experimentid, (int)typeid);
                                this.DataBindTemplates();
                            }
                            break;
                        }
                    case "Link":
                        {
                            int? experimentid = view_NonLinkedExperiments.DataKeys[(int)rowindex]["ID"] as int?;
                            if (experimentid != null && typeid != null)
                            {
                                this.LinkExperimentToType((int)experimentid, (int)typeid);
                                this.DataBindTemplates();
                            }
                            break;
                        }
                    default:
                        break;
                }
            }
        }

        private void LinkExperimentToType(int experimentid, int typeid)
        {
            MaterialsMetadataContext dbcontext = HttpContext.Current.GetMaterialsDBContext();
            ExperimentTypeExperimentTemplateMap newMap = dbcontext.CreateTypeExperimentLink(experimentid, typeid);
        }

        private void UnlinkExperimentFromType(int experimentid, int typeid)
        {
            MaterialsMetadataContext dbcontext = HttpContext.Current.GetMaterialsDBContext();
            dbcontext.DeleteTypeExperimentLink(experimentid, typeid);
            dbcontext.SaveChanges();
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                //Data bind Experiment Types
                this.DataBindExperimentTypes();
                //We can't data bind anything else until the user selects an experiment type
            }
        }

        private void view_ExperimentTypes_SelectedIndexChanged(object sender, EventArgs e)
        {
            int? selectedExperimentType = view_ExperimentTypes.SelectedDataKey["ID"] as int?;
            if (selectedExperimentType != null)
            {
                //Data bind the matching templates from the selected experiment type
                this.DataBindLinkedTemplates((int)selectedExperimentType);
                //Data bind the drop-down of non-linked templates
                this.DataBindNonLinkedTemplates((int)selectedExperimentType);
                //Get rid of the instructions
                this.label_Instructions.Visible = false;
            }
            else
            {
                this.Controls.Add(new Label() { Text = "Can't find ID data key" });
            }
        }


        //DATA BINDING

        private void DataBindExperimentTypes()
        {
            MaterialsMetadataContext dbcontext = HttpContext.Current.GetMaterialsDBContext();
            IQueryable<ExperimentType> experimentTypes = dbcontext.ExperimentTypes.Where(type => type.ID > 0);
            this.view_ExperimentTypes.DataSource = experimentTypes;
            this.view_ExperimentTypes.DataBind();
        }

        private void DataBindTemplates()
        {

            int? typeid = view_ExperimentTypes.SelectedDataKey["ID"] as int?;
            if (typeid != null)
            {
                this.DataBindLinkedTemplates((int)typeid);
                this.DataBindNonLinkedTemplates((int)typeid);
            }
        }

        private void DataBindLinkedTemplates(int experimentType)
        {
            MaterialsMetadataContext dbcontext = HttpContext.Current.GetMaterialsDBContext();
            IQueryable<Experiment> linkedExperiments = 
                dbcontext.ExperimentTypeExperimentTemplateMaps
                .Where(type=>type.ExperimentTypeID==experimentType).Select(type=>type.Experiment);
            this.view_LinkedTemplates.DataSource = linkedExperiments;
            this.view_LinkedTemplates.DataBind();
        }

        private void DataBindNonLinkedTemplates(int experimentType)
        {
            MaterialsMetadataContext dbcontext = HttpContext.Current.GetMaterialsDBContext();
            IQueryable<Experiment> nonLinkedExperiments =
                dbcontext.Experiments
                .Where(exp=>
                    //Only display templates
                    exp.ExperimentType.ID==(int)HDCExperimentTypes.Template
                    //Only display experiments that are not already mapped
                 && !dbcontext.ExperimentTypeExperimentTemplateMaps.Any(templatemap=>templatemap.TemplateExperimentID==exp.ID)
                    );
            this.view_NonLinkedExperiments.DataSource = nonLinkedExperiments;
            this.view_NonLinkedExperiments.DataBind();
        }

        protected void btn_CreateNewType_Click(object sender, EventArgs e)
        {
            //Get a connection to the database
            MaterialsMetadataContext context = HttpContext.Current.GetMaterialsDBContext();

            try
            {
                ExperimentType newType = context.CreateExperimentType(this.txt_NewExperimentName.Text);
                this.lbl_CreateExperimentTypeMessage.Text = newType.Name + " type created";
                this.DataBindExperimentTypes();
            }
            catch (NotSupportedException)
            {
                this.lbl_CreateExperimentTypeMessage.Text = "Experiment type exists";
            }
        }
    }
}
